package huu.phong.youtube;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.StringTokenizer;

import javax.imageio.ImageIO;
import javax.swing.SwingUtilities;


public class StoryBoard implements Serializable {
	
	private static final long serialVersionUID = 5689148073060204821L;
	public int width = 0;
	public int height = 0;
	public int total = 0;
	public int rows = 0;
	public int cols = 0;
	public String regrex;
	public int second = 0;
	public String sigh;
	public String id;
	public String link;
	public int quality = 1;
	private int durationWidth;
	private int durationHeight;
	
	private int numberThumbnail = 0;
	private int col = 0;
	private int row = 0;
	
	private transient Map<String, BufferedImage> images;
	private transient List<String> request;
	private transient Thread loadImages;
	private transient Queue<Thread> process;
	private transient BufferedImage result;
	
	public StoryBoard(String id, String line, String link, int quality){
		StringTokenizer token = new StringTokenizer(line, "#");
		width = new Integer(token.nextToken());
		height = new Integer(token.nextToken());
		total = new Integer(token.nextToken());
		rows = new Integer(token.nextToken());
		cols = new Integer(token.nextToken());
		second = new Integer(token.nextToken());
		regrex = token.nextToken();
		sigh = token.nextToken();
		this.link = link;
		this.quality = quality;
		this.id = id;
	}
	
	public BufferedImage getImage(final long second) throws MalformedURLException, IOException{
		if (sigh == null) return null;
		if (images == null){
			images = new HashMap<String, BufferedImage>();
			request = new ArrayList<String>();
			process = new ArrayDeque<Thread>();
			loadImages = new Thread(){
				public void run(){
					while (true){
						while (!process.isEmpty()){
							Thread thread = process.poll();
							thread.start();
							try {
								thread.join();
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
						}
						synchronized (loadImages) {
							try {
								loadImages.wait();
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
						}
					}
				}
			};
			loadImages.start();
			result = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
		}
		final String key = String.valueOf((second / this.second) / (rows * cols));
		if (images.get(key) == null && !request.contains(key)){
			request.add(key);
			getImage(null, second, result);
			process.add(new Thread(){
				public void run(){
					try {
						images.put(key, ImageIO.read(new URL(link + "sb/" + id + "/storyboard3_L" + quality + "/M" + key + ".jpg?sigh=" + sigh)));
					} catch (Exception e) {
						request.remove(key);
					}
				}
			});
			synchronized (loadImages) {
				loadImages.notifyAll();
			}
		}else{
			getImage(images.get(key), second, result);
		}
		return result;
	}
	
	private void getImage(BufferedImage image, long second, BufferedImage ret){
		Graphics2D g = ret.createGraphics();
		g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
		g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,	RenderingHints.VALUE_ANTIALIAS_ON);
		g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
		g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
		g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
		if (image != null){
			numberThumbnail = (int) ((second / this.second) % (rows * cols));
			col = (int) ((numberThumbnail / rows) * height);
			row = (int) ((numberThumbnail % rows) * width);
			g.drawImage(image, 0, 0, width, height, row, col, width + row, height + col, Color.BLACK, null);
			
		} else {
			g.setColor(Color.BLACK);
			g.fillRect(0, 0, width, height);
		}
		switch (quality) {
			case 1: g.setFont(YouTube.DEFAULT_FONT); break;
			case 2: g.setFont(YouTube.DEFAULT_FONT.deriveFont(16f)); break;
			case 3: g.setFont(YouTube.DEFAULT_FONT.deriveFont(20f)); break;
			default: g.setFont(YouTube.DEFAULT_FONT); break;
		}
		String duration = YouTubeAPI.toDuration(second / 1000);
		g.setColor(YouTube.DEFAULT_BACKGROUND);
		durationWidth = SwingUtilities.computeStringWidth(g.getFontMetrics(), duration);
		durationHeight = g.getFontMetrics().getAscent() - g.getFontMetrics().getDescent();
		g.fillRoundRect(width - (durationWidth + 8), height - (durationHeight + 8), durationWidth + 6, durationHeight + 6, 5, 5);
		g.setColor(Color.WHITE);
	    g.drawString(duration, width - (durationWidth + 5), height - 5);
	}
	
	public void clear(){
		images = null;
		request = null;
		loadImages = null;
		process = null;
	}
}
